package com.fw.common;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserCertdocCertverifyConsultResponse;
import com.alipay.api.response.AlipayUserCertdocCertverifyPreconsultResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import com.fw.config.AliConfig;
import com.fw.enums.AliPayEnum;
import com.fw.mes.AliAppUserAccToken;
import com.fw.mes.AliAppUserInfo;
import com.fw.utils.StringUtils;
import com.google.common.collect.Maps;
import com.ijpay.alipay.AliPayApi;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝 相关 支付 & 用户等
 */
@Slf4j
public class AliComm extends AliCommAbs {

    @Autowired
    private  AliConfig aliConfig;




    @Override
    public AliConfig getAliConfig() {
        return aliConfig;
    }

    /**
     *   单笔商家对个人付款
     *    最新版
     * @param aliAccount 收款人支付宝账号 .
     * @param amount     转账多少钱，元为单位.
     * @param realName   支付宝真实姓名
     * @throws AlipayApiException
     */
    public void aliTransfer(String aliAccount, BigDecimal amount,String realName) throws AlipayApiException {
        //AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel();
        AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
        model.setOutBizNo(UUID.fastUUID().toString(Boolean.TRUE));
        log.info("支付宝商家对个人转账: 收款人:{},收款金额:{}",aliAccount,amount);
        model.setProductCode("TRANS_ACCOUNT_NO_PWD");
        model.setPayeeInfo(Builder.of(Participant::new).with(Participant::setIdentity,aliAccount).with(Participant::setIdentityType,"ALIPAY_LOGON_ID").with(Participant::setName,realName).build());
        model.setTransAmount(amount.setScale(2,BigDecimal.ROUND_DOWN).toString());
        model.setOrderTitle("河南旷视网络科技有限公司");
        model.setBizScene("DIRECT_TRANSFER");
        String body = AliPayApi.uniTransferToResponse(model, null).getBody();
        //String body = AliPayApi.transferToResponse(model).getBody();
        Assert.isTrue(JSON.parseObject(body).getJSONObject("alipay_fund_trans_uni_transfer_response").getString("code").equals("10000"),body);
        log.info(body);
        log.info("支付宝商家对个人转账: 收款人:{},收款金额:{}",aliAccount,amount);
    }


    /**
     *   单笔商家对个人付款
     * @param aliAccount 收款人支付宝账号 .
     * @param amount     转账多少钱，元为单位.
     * @throws AlipayApiException
     */
    @Deprecated
    public void aliTransfer(String aliAccount, BigDecimal amount) throws AlipayApiException {
        AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel();
        model.setOutBizNo(UUID.fastUUID().toString(Boolean.TRUE));
        model.setPayeeType("ALIPAY_LOGONID");
        model.setPayeeAccount(aliAccount.trim());
        model.setAmount(amount.toString());
        model.setPayerShowName("河南旷视网络科技有限公司");
        model.setPayerRealName("河南旷视网络科技有限公司");
        String body = AliPayApi.transferToResponse(model).getBody();
        Assert.isTrue(JSON.parseObject(body).getJSONObject("alipay_fund_trans_toaccount_transfer_response").getString("code").equals("10000"),body);
        log.info(body);
        log.info("支付宝商家对个人转账: 收款人:{},收款金额:{}",aliAccount,amount);
    }





    /**
     * app支付
     * @param outTradeNo 平台唯一单号，用来回调进行锁定单号
     * @param amount      支付金额，元为单位
     * @param aliPayEnum  回调,内容枚举类
     * @return  app所需要在线调用的参数,直接返回app即可。
     * @throws AlipayApiException
     */
    public String appPay(String outTradeNo, BigDecimal amount,AliPayEnum aliPayEnum) throws AlipayApiException {

            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            model.setBody(aliPayEnum.getBody());
            model.setSubject("商甲商品");
            model.setOutTradeNo(outTradeNo);
            model.setTimeoutExpress("30m");
            model.setTotalAmount(amount.toString());
            model.setPassbackParams("callback params");
            model.setProductCode("QUICK_MSECURITY_PAY");
             String orderInfo = AliPayApi.appPayToResponse(model, getAliConfig().getDomain().concat(aliPayEnum.getNotifyUrl())).getBody();
            log.info("app支付返回支付参数为:{}",orderInfo);

        return orderInfo;
    }
    /**
     * app支付
     * @param outTradeNo 平台唯一单号，用来回调进行锁定单号
     * @param amount      支付金额，元为单位
     * @param aliPayEnum  回调,内容枚举类
     * @param passbackParams    公用回传参数
     * @return  app所需要在线调用的参数,直接返回app即可。
     * @throws AlipayApiException
     * @Author 姚
     */
    public String appPay(String outTradeNo, BigDecimal amount, AliPayEnum aliPayEnum, String passbackParams) throws AlipayApiException {
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody(aliPayEnum.getBody());
        model.setSubject("商甲商品");
        model.setOutTradeNo(outTradeNo);
        model.setTimeoutExpress("30m");
        model.setTotalAmount(amount.toString());
        model.setProductCode("QUICK_MSECURITY_PAY");
        model.setPassbackParams(passbackParams);
        String orderInfo = AliPayApi.appPayToResponse(model, getAliConfig().getDomain().concat(aliPayEnum.getNotifyUrl())).getBody();
        log.info("app支付返回支付参数为:{}",orderInfo);
        return orderInfo;
    }


    /**
     * app用户登陆
     * @param code 授权code 编码
     */
    public AliAppUserAccToken aliAppLogin(String code) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest());
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(code);
        AlipaySystemOauthTokenResponse response = alipayClient.certificateExecute(request);
        String body = response.getBody();
        log.info("app用户根据code 登陆,结果为:{}",body);
        if(response.isSuccess()){
            JSONObject oauthTokenResponse = JSON.parseObject(body).getJSONObject("alipay_system_oauth_token_response");
            AliAppUserAccToken aliAppUserAccToken = oauthTokenResponse.toJavaObject(AliAppUserAccToken.class);
         return aliAppUserAccToken;
        } else {
            log.info(body);
           throw new RuntimeException("调用失败!");
        }

    }

    /**
     * 根据 回话 token 得到用户信息
     * @param accessToken  回话token
     */
    public AliAppUserInfo getAliUserInfo(String accessToken) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest());
        AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
        AlipayUserInfoShareResponse response = alipayClient.certificateExecute(request,accessToken);
        String body = response.getBody();
        log.info("app用户根据accessToken 获取用户信息,结果为:{}",body);
        if(response.isSuccess()){
            JSONObject oauthTokenResponse = JSON.parseObject(body).getJSONObject("alipay_user_info_share_response");
            AliAppUserInfo aliAppUserInfo = oauthTokenResponse.toJavaObject(AliAppUserInfo.class);
            return aliAppUserInfo;
        } else {
            log.info(body);
            throw new RuntimeException("调用失败!");
        }
    }

    /**
     *  根据 基础信息 获取 verifyId
     */
    public String getVerifyId(Map<String,Object> parMaps) throws AlipayApiException{
        AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest());
        AlipayUserCertdocCertverifyPreconsultRequest request = new AlipayUserCertdocCertverifyPreconsultRequest();
        parMaps.put("cert_type","IDENTITY_CARD");
        request.setBizContent(JSON.toJSONString(parMaps));
        AlipayUserCertdocCertverifyPreconsultResponse response = alipayClient.certificateExecute(request);
        if(response.isSuccess()){
           return response.getVerifyId();
        } else {
            throw new RuntimeException(StringUtils.format("失败原因:{}",response.getMsg()));
        }

    }

    /**
     *
     * @param token
     * @param verifyId
     * @return
     * @throws AlipayApiException
     */
    public AlipayUserCertdocCertverifyConsultResponse consult(String token,String verifyId) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest());
        AlipayUserCertdocCertverifyConsultRequest request = new AlipayUserCertdocCertverifyConsultRequest();
        HashMap<Object, Object> parMaps = Maps.newHashMap();
        parMaps.put("verify_id",verifyId);
        request.setBizContent(JSON.toJSONString(parMaps));
        AlipayUserCertdocCertverifyConsultResponse response = alipayClient.certificateExecute(request,token);
        if(response.isSuccess()){
            System.out.println("调用成功");
            return response;
        } else {
            throw new RuntimeException(StringUtils.format("失败原因:{}",response.getMsg()));
        }

    }

    /**
     * 证书模式
     */
    private CertAlipayRequest certAlipayRequest(){
        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        certAlipayRequest.setServerUrl(getAliConfig().getServiceUrl());
        certAlipayRequest.setAppId(getAliConfig().getAppId());
        certAlipayRequest.setPrivateKey(getAliConfig().getPrivateKey());
        certAlipayRequest.setCharset("utf-8");
        certAlipayRequest.setFormat("json");
        certAlipayRequest.setSignType("RSA2");
        certAlipayRequest.setCertPath(getAliConfig().getAppCertPath());
        certAlipayRequest.setAlipayPublicCertPath(getAliConfig().getAliPayCertPath());
        certAlipayRequest.setRootCertPath(getAliConfig().getAliPayRootCertPath());
        return certAlipayRequest;
    }

}
